/*
 * DecoderManager.cpp
 *
 *  Created on: 2011-3-1
 *      Author: hao
 */
#include "DecoderManager.h"

#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string>
#include <iostream>
#include <fcntl.h>

using std::string;

DecoderMaster::DecoderMaster() {

    //pMachine = NULL;

}

DecoderMaster::~DecoderMaster() {

}

int DecoderMaster::SetupDecodingFile(void * pData, size_t length, unsigned * pchannel, unsigned * prate, unsigned * pformat ) {

    int index = 0;

    int Truecount = 0; //Match decoder count;

    std::function<bool(void *, unsigned long long) > check;

    for (unsigned i = 0; i < vDecoder.size(); i++) {

        check = vDecoder[i]->getCheckingFunction();

        if (check(pData, length)) {
            Truecount++;
            index = i;
            break;
        }

    }

    if (Truecount != 1) {
        return -1;
    }

    vDecoder[index]->getSoundStatusFunction()(pformat, pchannel, prate);

    if (!vDecoder[index]->getSetTrack()(0, 0, 0, -1, -1, -1)) return -1;

    return index;

}

int DecoderMaster::SetupDecodingTrack(void * pData, size_t length, unsigned * pchannel, unsigned * prate, unsigned * pformat, const CueSheet & sheet, unsigned TrackIndex) {
    
    int index = 0;

    int Truecount = 0;

    std::function<bool(void *, unsigned long long) > check;

    for (unsigned i = 0; i < vDecoder.size(); i++) {

        check = vDecoder[i]->getCheckingFunction();

        if (check(pData, length)) {
            Truecount++;
            index = i;
            break;
        }

    }

    if (Truecount != 1) {
        return -1;
    }

    vDecoder[index]->getSoundStatusFunction()(pformat, pchannel, prate);

    if ( TrackIndex == sheet.TrackList.size() - 1 || sheet.TrackList[TrackIndex].fileIndex != sheet.TrackList[TrackIndex+1].fileIndex) {
        if (!vDecoder[index]->getSetTrack()(sheet.TrackList[TrackIndex].Min,
                sheet.TrackList[TrackIndex].Second,
                sheet.TrackList[TrackIndex].Frame, -1, -1, -1)) return -1;
    } else if (sheet.TrackList[TrackIndex + 1].SpaceFrame
            || sheet.TrackList[TrackIndex + 1].SpaceSecond
            || sheet.TrackList[TrackIndex + 1].SpaceMin) {
        if (!vDecoder[index]->getSetTrack()(sheet.TrackList[TrackIndex].Min,
                sheet.TrackList[TrackIndex].Second,
                sheet.TrackList[TrackIndex].Frame, sheet.TrackList[TrackIndex
                + 1].SpaceMin,
                sheet.TrackList[TrackIndex + 1].SpaceSecond,
                sheet.TrackList[TrackIndex + 1].SpaceFrame)) return -1;
    } else {
        if (!vDecoder[index]->getSetTrack()(sheet.TrackList[TrackIndex].Min,
                sheet.TrackList[TrackIndex].Second,
                sheet.TrackList[TrackIndex].Frame, sheet.TrackList[TrackIndex
                + 1].Min, sheet.TrackList[TrackIndex + 1].Second,
                sheet.TrackList[TrackIndex + 1].Frame)) return -1;
    }

    return index;
    
}

bool DecoderMaster::Decoding(int index, void* pData, size_t length, size_t* pWriteLength){
    if( (unsigned)index >= vDecoder.size() ) return false;

    return vDecoder[index]->getDecodingFunction()( pData, length, pWriteLength );

}
void DecoderMaster::getDecoderingFileTotalTime(int index, int* pMin, int* pSeconds, int* pFrame){
    
    if( (unsigned)index >= vDecoder.size() ) return;
    
    vDecoder[index]->getTotalTime()( pMin, pSeconds, pFrame );
    
}

bool DecoderMaster::Seek(int index, int min, int second, int frame){
    if( (unsigned)index >= vDecoder.size() ) return false;
    
    return vDecoder[index]->getSeek()( min, second, frame );
}




std::string DecoderMaster::getSurportPrefixName() {

    std::string temp;

    for (unsigned i = 0; i < vDecoder.size(); i++) {
        
        temp += "*.";

        const string & prefixname = vDecoder[i]->getPrefixName();
        for( unsigned i = 0; i < prefixname.size(); i++ ){
            temp += prefixname[i];
            if( prefixname[i] == ' ' )
                temp += "*.";
        }
        
        temp += " ";

    }

    return temp;
}